﻿using LeRenard.Core.Numbers;
using System;
using Xunit;

namespace LeRenard.Core.Tests.Numbers
{
    public class Int32RangeCyclerTests
    {
        [Fact]
        public void Current_Returns_Correct_Value()
        {
            // Arrange
            var range = new Int32Range();
            var expected = range.Minimum + 2;
            var sut = new Int32RangeCycler(range);

            // Act
            sut.Next();
            sut.Next();
            var actual = sut.Current;

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Next_Returns_MinimimValue_On_First_Call()
        {
            // Arrange
            var range = new Int32Range();
            var expected = range.Minimum;
            var sut = new Int32RangeCycler(range);

            // Act
            var actual = sut.Next();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Previous_Returns_MinimimValue_On_First_Call()
        {
            // Arrange
            var range = new Int32Range();
            var expected = range.Minimum;
            var sut = new Int32RangeCycler(range);

            // Act
            var actual = sut.Previous();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Peek_Returns_Value_After_MinimimValue_On_First_Next_Call()
        {
            // Arrange
            var range = new Int32Range(0, 9);
            var expected = range.Minimum + 1;
            var sut = new Int32RangeCycler(range);

            // Act
            var actual = sut.Next();
            actual = sut.Peek();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Next_Returns_Second_Value_On_Second_Call()
        {
            // Arrange
            var range = new Int32Range();
            var expected = range.Minimum + 1;
            var sut = new Int32RangeCycler(range);

            // Act
            var actual = sut.Next();
            actual = sut.Next();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Previous_Returns_Maximum_Value_On_Second_Call()
        {
            // Arrange
            var range = new Int32Range();
            var expected = range.Maximum;
            var sut = new Int32RangeCycler(range);

            // Act
            var actual = sut.Previous();
            actual = sut.Previous();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Next_Returns_MinimimValue_When_MaximumValue_Is_Reached()
        {
            // Arrange
            var range = new Int32Range(0, 9);
            var expected = range.Minimum;
            var sut = new Int32RangeCycler(range);
            sut.Reset(range.Maximum);

            // Act
            var actual = sut.Next();
            actual = sut.Next();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Previous_Returns_MaximumValue_When_MinimumValue_Is_Reached()
        {
            // Arrange
            var range = new Int32Range(0, 9);
            var expected = range.Maximum;
            var sut = new Int32RangeCycler(range);
            sut.Reset();

            // Act
            var actual = sut.Previous();
            actual = sut.Previous();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Reset_Sets_Counter_To_MinimumValue()
        {
            // Arrange
            var range = new Int32Range(0, 9);
            var expected = range.Minimum;
            var sut = new Int32RangeCycler(range);
            sut.Reset();

            // Act
            var actual = sut.Next();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Reset_Sets_Counter_To_MinimumValue_When_ProvidedValue_Exceeds_MaximumRange()
        {
            // Arrange
            var range = new Int32Range(0, 9);
            var expected = range.Minimum;
            var sut = new Int32RangeCycler(range);
            sut.Reset(10);

            // Act
            var actual = sut.Next();

            // Assert
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void Reset_Sets_Counter_To_MinimumValue_When_ProvidedValue_Exceeds_MinimumRange()
        {
            // Arrange
            var range = new Int32Range(0, 9);
            var expected = range.Minimum;
            var sut = new Int32RangeCycler(range);
            sut.Reset(-1);

            // Act
            var actual = sut.Next();

            // Assert
            Assert.Equal(expected, actual);
        }
    }
}
